package com.xiaomaoguai.fcp.pre.kepler.convert.core.support.adapter;

import com.dh.convert.exception.ValidateException;
import com.dh.convert.mapping.BeanMapping;
import com.google.common.collect.ImmutableMap;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.xiaomaoguai.fcp.pre.kepler.convert.core.ConvertManager;
import com.xiaomaoguai.fcp.pre.kepler.convert.core.support.ConvertSupport;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

/**
 * @fileName: AbstractConvertMethod.java
 * @author: WeiHui
 * @date: 2018/11/26 10:21
 * @version: v1.0.0
 * @since JDK 1.8
 */
@Slf4j
public abstract class AbstractConvertMethod implements IConvertMethod {

	/**
	 * 根据 各转node 表达式 各转
	 *
	 * @param convertSupport zk各转节点名称
	 * @param nodeName       zk各转节点名称
	 * @param root           元数据
	 * @return 各转返回值
	 */
	@SuppressWarnings("unchecked")
	protected Object convert(ConvertSupport convertSupport, String nodeName, Object root) {
		Object result;
		try {
			BeanMapping beanMapping = ConvertManager.getBeanMapping(nodeName);
			if (beanMapping != null) {
				result = ConvertSupport.getConvert(convertSupport).convert(root, beanMapping.getTargetNode());
			} else {
				result = root;
			}
		} catch (ValidateException e) {
			throw new IllegalArgumentException(e.getMessage() + " nodename:" + nodeName, e);
		} catch (Exception e) {
			log.error("格转异常，格转名为:{}", nodeName, e);
			throw new RuntimeException(e);
		}
		return result;
	}

	/**
	 * 通用解析方法
	 *
	 * @param el    avitor 表达式节点
	 * @param root  原始参数
	 * @param clazz 目标对象
	 * @param <T>   目标对象范型
	 * @return 目标对象
	 */
	@SuppressWarnings("unchecked")
	protected <T> T parserAvExpression(String el, String convertParam, Object root, Class<T> clazz) {
		Expression expression = AviatorEvaluator.compile(el,true);
		try {
			Map<String, Object> env;
			if (StringUtils.isBlank(convertParam)) {
				env = (Map<String, Object>) root;
			} else {
				env = ImmutableMap.of(convertParam, root);
			}
			return (T) expression.execute(env);
		} catch (Exception e) {
			throw new RuntimeException("各转入参类型错误，（1）要么参数是Map<String, Object>类型(2)要么为参数设置别名，av表达式加别名前缀", e);
		}
	}

	/**
	 * 通用解析方法
	 *
	 * @param el    avitor 表达式节点
	 * @param root  原始参数
	 * @param clazz 目标对象
	 * @param <T>   目标对象范型
	 * @return 目标对象
	 */
	protected <T> T buildDataByEl(String el, String convertParam, Object root, Class<T> clazz) {
		return buildData(parserAvExpression(el, convertParam, root, String.class), root, clazz);
	}

	/**
	 * 通用解析方法
	 *
	 * @param nodeName 节点名称
	 * @param root     原始参数
	 * @param clazz    目标对象
	 * @param <T>      目标对象范型
	 * @return 目标对象
	 */
	@SuppressWarnings("unchecked")
	protected <T> T buildData(String nodeName, Object root, Class<T> clazz) {
		BeanMapping beanMapping = ConvertManager.getBeanMapping(nodeName);
		if (beanMapping == null || beanMapping.getTargetNode() == null) {
			throw new IllegalArgumentException("无法取得字段格转组，请检查配置!");
		}
		try {
			return (T) ConvertSupport.getBeanConvertByClass(clazz).convert(root, beanMapping.getTargetNode());
		} catch (ValidateException e) {
			throw new IllegalArgumentException(e.getMessage(), e);
		} catch (Exception e) {
			log.error("格转异常", e);
			throw new IllegalArgumentException(e);
		}
	}

}
